var express = require("express");
var uunewid = require("uuid");
var router = express.Router();
const multer = require("multer");
var { checkProperty, checkAuth } = require("../utils/utils");
const jwt = require("jsonwebtoken");
var { PUBLICKEY, EXPIRESD } = require("../utils/store");
var moment = require("moment");

const fs = require("fs");

let log = require("cf-nodejs-logging-support");
log.setLoggingLevel("info");

var constants = require("../utils/constants");

const { ohana } = require("ohana-node-orm");

const tableName = constants.REGISTEDUSERSTABLE;
const ohana_instance = new ohana(tableName);

const axios = require("axios");

// 获取 access_token, 过期时间 7200s
const MP = {
  appid: "wxe5886d1b9a1b5225",
  appsecret: "98e7312ebb897325bbbe4b76c1ee4f13",
};
const urlString =
  "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" +
  MP.appid +
  "&secret=" +
  MP.appsecret;
let accessToken = "";

function getAccessToken() {
  axios.get(urlString).then((res) => {
    accessToken = res.data.access_token;
    fs.writeFile("./file/access_token.txt", accessToken, (err) => {
      if (err) {
        console.error(err);
        return;
      }
    });
  });
}
getAccessToken();
setInterval(() => {
  getAccessToken();
}, 3600000);

// 仅供临时测试使用
router.get("/ws-test", (req, res) => {
  res.sendFile(__dirname + "/wechat.html");
});

// 手动刷新 access token
router.get("/refresh-access-token", (req, res) => {
  getAccessToken();
  res.send(accessToken);
});

router.get("/scan-login-img", function (req, res) {
  // timestamp = Number(new Date()), 表示从 desktop web 访问
  if (req.query.timestamp && accessToken) {
    // to-do: 小程序正式版发布后需随机生成 key
    // to-do: img 需通过小程序接口 wxacode.getUnlimited 根据 key 生成

    const k = String(Math.floor(Math.random() * 10000000));

    // https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN
    axios
      .post(
        "https://api.weixin.qq.com/wxa/getwxacode?access_token=" + accessToken,
        {
          path: "pages/wechatscanlogin/index?type=open&targeturl=/s-l/" + k,
          // page: "pages/wechatscanlogin/index",
          // scene: "type=open&targeturl=/s-l/" + k,
          // env_version: "trial"
        },
        {
          responseType: "arraybuffer",
        }
      )
      .then((wxRes) => {
        res.send({
          img: wxRes.data.toString("base64"),
          // ioLink: "http://localhost:4000",
          ioPath: "/io",
          key: k,
        });
      });
  } else {
    res.sendStatus(404);
  }
});

router.get("/scan-login", async function (req, res, next) {
  // 携带 key 和 code 表示从小程序访问
  if (req.query.key && req.query.code) {
    const io = req.app.get("socketio");

    let result = { status: "", value: "" };

    result.status = "SCAN_START";
    io.emit(req.query.key, result);

    const openid = await code2id(req.query.code);
    const user = await id2user(openid);

    // to-do: 通过 openid 查询已绑定用户并签发 token

    // to-do-1: 登录页从服务端获取一个带 key 参数的小程序码
    // to-do-2: key 用于创建 WebSocket
    // to-do-3: 将小程序码和 WS 地址返回给登录页
    // to-do-4: 登录页显示小程序码并建立 WS 连接
    // to-do-5: 小程序端扫码, code 传递给微信换取 openID, key 参数定位 WS 地址
    // to-do-6: 上述工作完成后, res.send 告知小程序
    // to-do-7: 将 token 签发给目标 WS client

    if (user) {
      result.status = "SCAN_LOGIN_OK";
      result.value = user;
    } else {
      result.status = "NOT_BINDING";
      result.value = { openid: openid };
    }
    io.emit(req.query.key, result);
    res.send(result);
  } else {
    res.sendStatus(404);
  }
});

// router.get("/code2id", async (req, res) => {
//   if (req.query.code) {
//     const wechatID = await code2id(req.query.code)
//     res.send(wechatID.data)
//   } else {
//     res.sendStatus(404)
//   }
// })

router.get("/code2user", async (req, res) => {
  if (req.query.code) {
    const openid = await code2id(req.query.code);
    const user = await id2user(openid);

    if (user) {
      // 查询到 user
      res.send(user);
    } else {
      // 未查询到 user, 返回 openid
      res.send({ openid });
    }
  } else {
    res.sendStatus(404);
  }
});

async function code2id(code) {
  const code2id = `https://api.weixin.qq.com/sns/jscode2session?appid=${MP.appid}&secret=${MP.appsecret}&js_code=${code}&grant_type=authorization_code`;
  const wechatID = await axios.get(code2id);
  return wechatID.data.openid;
}

async function id2user(id) {
  try {
    const result = await ohana_instance.findOne({
      WUID: id,
    });
    if (result && result.length !== 0) {
      const r = result[0];
      let faceData = { status: false };
      try {
        faceData = JSON.parse(r.FACE_IDENTITY_STATUS);
        if (faceData === null) {
          faceData = {
            status: false,
          };
        }
      } catch (error) { }
      return {
        code: 0,
        status: "OK",
        USER_NAME: r.USER_NAME,
        STATUS: r.STATUS,
        COMPANY_NAME: r.COMPANY_NAME,
        LEVEL: r.LEVEL,
        AUTH: r.AUTH,
        USER_ID: r.USER_ID,
        FACE_IDENTITY_STATUS: faceData.status ? faceData.status : false,
        token: generateToken({
          USER_NAME: r.USER_NAME,
          USER_ID: r.USER_ID,
          LEVEL: r.LEVEL,
          AUTH: r.AUTH,
          COMPANY_NAME: r.COMPANY_NAME,
          FACE_IDENTITY_STATUS: faceData.status ? faceData.status : false,
          status: "ok",
        }),
        message: "passed",
      };
    } else {
      return null;
    }
  } catch (error) {
    return null;
  }
}

function generateToken(userData) {
  const token =
    "Bearer " +
    jwt.sign(
      {
        _id: userData.USER_ID,
        name: userData.USER_NAME,
        role: userData.AUTH,
        company: userData.COMPANY_NAME,
        level: userData.LEVEL,
        face: userData.FACE_IDENTITY_STATUS,
      },
      PUBLICKEY,
      {
        expiresIn: EXPIRESD,
      }
    );
  return token;
}

module.exports = router;
